#pragma once
#include <iostream>
#include <string.h>
using namespace std;
#include <sys/types.h>
#include <sys/socket.h>

#include <netinet/in.h>
#include <arpa/inet.h>

const static int g_socket = -1;
const static int g_port = 8080;
const static std::string g_default_ip = "127.0.0.1";


class udpServer
{
private:
    int _socket;
    int16_t _port;
    std::string _ip;
    bool isRunning;
public:
    udpServer(int16_t port = g_port,string ip = g_default_ip,int socket = g_socket)
        :_port(port)
        ,_ip(ip)
        ,_socket(socket)
        ,isRunning(false)
    {}

    ~udpServer()
    {
    }

    void Init()
    {
        //1.创建套接字
        _socket = ::socket(AF_INET,SOCK_DGRAM,0);   //网络、数据报
        if(_socket == 0)
        {
            cout << "1.创建socket失败" << endl;
            return;
        }
        cout << "create socket success fd: " << _socket << endl;

        //2. 绑定端口号与ip地址
        struct sockaddr_in  InetAddr;
            //2.1设置端口号与ip
        bzero(&InetAddr,sizeof(InetAddr));
        InetAddr.sin_family = AF_INET;
        InetAddr.sin_port = ::htons(_port);
        InetAddr.sin_addr.s_addr = ::inet_addr(_ip.c_str());
            //2.2 绑定
        int n = ::bind(_socket,(sockaddr*)(&InetAddr),sizeof(InetAddr));

        if(n == -1)
        {
            cout << "2. 绑定失败" << endl;
            return;
        }

        cout << "bind success" << endl;
    }

    void Start()
    {
        if(!isRunning)
        {
            isRunning = true;
            while(true)
            {
                struct sockaddr_in fromUser;
                socklen_t len = sizeof(fromUser);
                char buffer[1024];
                //3. 接收信息
                int n = ::recvfrom(_socket,&buffer,sizeof(buffer),0,(sockaddr*)(&fromUser),&len);
                if(n > 0)
                {   
                    buffer[n] = '\0';

                    //获取发送者的信息
                    uint16_t clientPort = ::ntohs(fromUser.sin_port);
                    string clientIp = ::inet_ntoa(fromUser.sin_addr);

                    string message =  clientIp + ":" + to_string(clientPort) + "#";
                    message += buffer;
                    cout << message << endl;

                    std::string echoString = "echo say#";
                    echoString += buffer;
                    // 将消息在回显给发送方
                    ::sendto(_socket,echoString.c_str(),echoString.size(),0,(sockaddr*)&fromUser,len);
                }
            }
        }
        isRunning = false;
    }
};